package net.sudot.chess.business.service;

import net.sudot.chess.business.dao.PaymentTransactionDao;
import net.sudot.chess.business.dto.PaymentItemDTO;
import net.sudot.chess.business.model.OrderRecharge;
import net.sudot.chess.business.model.PaymentTransaction;
import net.sudot.chess.constant.LockConstants;
import net.sudot.chess.plugin.payment.PaymentPlugin;
import net.sudot.commons.lock.Lock;
import net.sudot.commons.utils.SnowflakeIdWorker;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.temporal.ChronoUnit;

/**
 * 支付事务
 *
 * @author tangjialin on 2018-03-20.
 */
@Service
public class PaymentTransactionService extends BaseService<PaymentTransaction> {

    @Resource(name = "paymentTransactionServiceSnowflakeIdWorker")
    private SnowflakeIdWorker snowflakeIdWorker;
    @Resource
    private PaymentTransactionDao paymentTransactionDao;
    @Resource
    private OrderRechargeService orderRechargeService;

    /**
     * 获取支付事务
     *
     * @param sn 支付事务编号
     * @return 返回支付事务
     */
    public PaymentTransaction findBySn(String sn) {
        return paymentTransactionDao.find("sn", sn);
    }

    /**
     * 获取支付事务
     *
     * @param type   类型
     * @param target 支付对象
     * @return 返回支付事务
     */
    public PaymentTransaction findByTarget(PaymentTransaction.Type type, Long target) {
        return paymentTransactionDao.findByTarget(type, target);
    }

    /**
     * 生成支付事务
     *
     * @param itemDTO       支付项
     *                      itemDTO.type    :(必需)支付类型
     *                      itemDTO.orderSn :(必需)订单编号
     *                      itemDTO.amount  :(必需)支付金额
     *                      itemDTO.userId  :(必需)支付用户
     *                      itemDTO.target  :(必需)支付对象
     * @param paymentPlugin 支付插件
     * @return 可用支付事务，若不存在则返回null
     */
    @Transactional(rollbackFor = Exception.class)
    public PaymentTransaction generate(PaymentItemDTO itemDTO, PaymentPlugin paymentPlugin) {
        PaymentTransaction paymentTransaction = paymentTransactionDao.findAvailable(itemDTO, paymentPlugin);
        if (paymentTransaction == null) {
            paymentTransaction = new PaymentTransaction();
            paymentTransaction.setType(itemDTO.getType());
            paymentTransaction.setAmount(paymentPlugin.calculateAmount(itemDTO.getAmount()));
            paymentTransaction.setSuccess(false);

            Instant instant = Instant.now().plus(paymentPlugin.getTimeout(), ChronoUnit.SECONDS);
            paymentTransaction.setExpire(instant);

            paymentTransaction.setUserId(itemDTO.getUserId());
            paymentTransaction.setPaymentPluginId(paymentPlugin.getId());
            paymentTransaction.setPaymentPluginName(paymentPlugin.getName());
            paymentTransaction.setTarget(itemDTO.getTarget());
            save(paymentTransaction);
        }
        return paymentTransaction;
    }


    /**
     * 支付处理
     *
     * @param transaction 支付事务
     */
    @Transactional(rollbackFor = Exception.class)
    @Lock(name = LockConstants.PAYMENT_TRANSACTION, value = "#transaction.id")
    public void handle(PaymentTransaction transaction) {
        if (transaction.getSuccess()) {
            return;
        }

        switch (transaction.getType()) {
            case RECHARGE:
                OrderRecharge order = orderRechargeService.find(transaction.getTarget());
                if (order != null) {
                    orderRechargeService.payment(order, transaction);
                }
                break;
//            case BAIL:
//                break;
            default:
                throw new UnsupportedOperationException("不支持的订单类型");
        }
        transaction.setSuccess(true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentTransaction save(PaymentTransaction paymentTransaction) {
        paymentTransaction.setSn(snowflakeIdWorker.getStringId());
        return super.save(paymentTransaction);
    }
}